#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>

#include "/home/hrj/include/Log.hpp" // log module 
#include "Common.hpp"   // the some import interface
#include "SockAddr.hpp"

// log by hrj by 2025/1/17
// it provide a class for to Create the socket more easyly
// I will provide more interface for windows and even macos in the future
// this version is just for Linux 

// version1.0 by hrj

namespace SocketModule
{
    
    
    
    using namespace LogModule;
    using namespace SockAddrModule;

    class Socket
    {
    public:
        virtual ~Socket() = default;
        virtual int SockOrDie() = 0;
        virtual void SetSockOpt() = 0;
        virtual bool BindOrDie() = 0;
        virtual bool ListenOrDie() = 0;
        virtual int Accept(SockAddr*) = 0;
        virtual ssize_t SendTo(const std::string&) = 0;
        virtual bool Recv(std::string* cotent) = 0;


        static void Close(int sockfd)
        {
            if(sockfd < 0) return;
            ::close(sockfd); // 关闭套接字
        }
        // 其他的方法通过继承后在加

        void BuildTcpSocket(int port)
        {
            SockOrDie();
            SetSockOpt();
            BindOrDie();
            ListenOrDie();
        }
        //
        void BuildUdpSock()
        {
            // nothing now 
        }

    private:
    };
    
    
    class TcpSocket : public Socket
    {
    public:
        TcpSocket(uint16_t port) : _port(port),_sockaddr_local(port)  // 声明的前后可能出现问题
        {}
        virtual int SockOrDie() override
        {
            _sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
            if(_sockfd < 0)
            {   
                LOG(LogLevel::FATAL) << "create sockfd fail";
                ::exit(SOCK_ERR);
            }
            LOG(LogLevel::DEBUG) << "create success";
            return true;
        }

        virtual bool BindOrDie() override
        {
            return Bind(_sockaddr_local,_sockfd);
        }

        virtual bool ListenOrDie() override
        {
            if(_sockfd < 0)
            {
                LOG(LogLevel::ERROR) << "wrong sockfd";
                exit(WRONG_SOCK);
            }
            return Listen(_sockfd);
        }
        virtual void SetSockOpt() override
        {
            // nothing in version1.0
        }
        // 这里可以把数据给到上端
        virtual int Accept(SockAddr* client) override
        {
            // 由于tcp是全双工的因此Accept的结果才是我们进行转发的sock
            SockAddr sockaddr_peer;
            socklen_t len = sockaddr_peer.SockAddrLen();
            LOG(LogLevel::DEBUG) << " sockfd : " << _sockfd;
            _sock_for_communicate = ::accept(_sockfd,sockaddr_peer.Convert(),&len);
            if(_sock_for_communicate < 0)
            {
                LOG(LogLevel::ERROR) << "accept fail:" << strerror(errno);
                ::exit(ACCEPT_ERR);
            }
            LOG(LogLevel::DEBUG) << "accept successfully";
            client->InitSockAddr(sockaddr_peer.Content());
            return 0;
        }

        
        // virtual void Close()
        // {
        //     if(_sockfd < 0)
        //         return;
        //     else ::close(_sockfd);
        // }
         virtual ssize_t SendTo(const std::string& content) override
        {
            ssize_t size = ::send(_sock_for_communicate,content.c_str(),content.size(),0);
            return size;
        }

        virtual bool Recv(std::string* content) override
        {
            char buffer[DEFAULT_BUFFER_SIZE] = { 0 };

            int ret = ::recv(_sock_for_communicate,buffer,sizeof(buffer) - 1,0);
            if(ret < 0)
            {
                LOG(LogLevel::ERROR) << "receiva data error";
                return false;
            }
            LOG(LogLevel::DEBUG) << "recv success";
            
            buffer[ret] = 0;
            *content = buffer;
            std::cout << "接受到的http请求:" << *content << std::endl;
            return true;
        }

        int SockForCommunicate() { return _sock_for_communicate; }
        int SockForListen() { return _sockfd; }
    private:
        int _sock_for_communicate;  // this socket is for communicate
        int _sockfd;  // this socket is just for listen 
        uint16_t _port;
        SockAddr _sockaddr_local;  // 构建本地sockaddr对象
        // SockAddr _sockaddr_peer; // 这里存在的问题是，如果的后续采取多线程的方式
        // 当多个执行流同时访问的时候，可能会出现错误
        // version1.0暂时还是采取detach的孤儿进程的方式
    };
}